package com.quanxiaoha.weblog.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.quanxiaoha.weblog.common.domain.entity.ScheduleRecord;
import com.quanxiaoha.weblog.common.domain.mapper.SchedulePaymentMapper;
import com.quanxiaoha.weblog.common.domain.mapper.ScheduleRewardMapper;
import com.quanxiaoha.weblog.common.domain.mapper.ScheduleSkillMapper;
import com.quanxiaoha.weblog.common.domain.query.RewardQuery;
import com.quanxiaoha.weblog.common.domain.vo.PointVo;
import com.quanxiaoha.weblog.common.domain.entity.ScheduleReward;
import com.quanxiaoha.weblog.common.entity.SchedulePayment;
import com.quanxiaoha.weblog.common.service.IScheduleHabitService;
import com.quanxiaoha.weblog.common.service.ISchedulePaymentService;
import com.quanxiaoha.weblog.common.service.IScheduleRewardService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.quanxiaoha.weblog.common.service.ScheduleRecordService;
import com.quanxiaoha.weblog.common.utils.AddictiveLottery;
import com.quanxiaoha.weblog.common.utils.LuckyDraw;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.security.SecureRandom;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Roy
 * @since 2025-06-06
 */
@Service
@Slf4j
public class ScheduleRewardServiceImpl extends ServiceImpl<ScheduleRewardMapper, ScheduleReward> implements IScheduleRewardService {

    @Autowired
    private ScheduleRecordService scheduleRecordService;

    @Autowired
    private ISchedulePaymentService schedulePaymentService;

    @Autowired
    private SchedulePaymentMapper schedulePaymentMapper;

    @Autowired
    private IScheduleHabitService  scheduleHabitService;

    @Resource
    ThreadPoolTaskExecutor taskExecutor;

    @Override
    public void init() {

        ScheduleReward scheduleReward = new ScheduleReward();
        scheduleReward.setRecordDate(LocalDate.now().toString());
//        scheduleReward.setRecordDate("2025-06-14");
        scheduleReward.setTotalReward(0);
        scheduleReward.setConCount(1);
        scheduleReward.setCreateTime(LocalDateTime.now());
        save(scheduleReward);
        log.info("每日初始化奖励成功");
        //初始化余额
        payment(scheduleReward);
        //初始化习惯
        scheduleHabitService.initToday();
    }

    @Async("taskExecutor")
    @Transactional(rollbackFor = Exception.class)
    void payment(ScheduleReward scheduleReward){

        try {
            //把昨天的数据转移到今天
            LambdaQueryWrapper<ScheduleReward> qw = new LambdaQueryWrapper<>();
            qw.eq(ScheduleReward::getRecordDate, LocalDate.now().minusDays(1).toString());
            ScheduleReward yesterday = this.getOne(qw);
            if(Objects.isNull(yesterday)) return;
            Integer resCount = 0;
            if(yesterday.getTotalReward()>0){
                resCount = scheduleReward.getTotalReward()+yesterday.getTotalReward();
            }else{
                resCount = scheduleReward.getTotalReward()+yesterday.getTotalReward();
            }
            //计算分期
            List<SchedulePayment> payments = schedulePaymentMapper.getPayments();
            for (SchedulePayment x : payments) {
                //计算分期
                int count = (int) x.getTotalReward() / x.getTotalCount();
                resCount = resCount +count;
                x.setCurrentCount(x.getCurrentCount()+1);
            }
            scheduleReward.setTotalReward(resCount);
            this.updateById(scheduleReward);
            schedulePaymentService.saveOrUpdateBatch(payments);
        }catch (Exception e){
            log.error(e.getMessage());
        }
    }

    @Override
    public PointVo getPoint(Integer tagId) {

        Integer minutes = getMinutes();
        if(minutes<5) throw new RuntimeException("任务时长不足5分钟，无法获得奖励");
        LambdaQueryWrapper<ScheduleReward> qw = new LambdaQueryWrapper<>();
        qw.eq(ScheduleReward::getRecordDate, LocalDate.now());
        ScheduleReward one = this.getOne(qw);
        if(Objects.isNull(one)) return null;

        //先返回对象
        PointVo pointVo = new PointVo();

        // 计算基础积分
        double random = new SecureRandom().nextDouble();
        int basePoints = AddictiveLottery.calculateWeightedRandomPoint(random);
        double bonus =  0.0;
        //算分规则
        switch (tagId){
            case 1:{
                // 计算加成
                bonus = AddictiveLottery.calculateBonus(one.getConCount()-1);
                pointVo.setConCount(one.getConCount());
//                // 计算工作学习轮次
//                if(one.getConCount()==6){
//                    one.setConCount(1);
//                }else{
//                    one.setConCount(one.getConCount()+1);
//                }
                break;
            }
            case 6:{
                // 计算加成
                bonus = AddictiveLottery.calculateBonus(0)*0.5;
                break;
            }
            case 7:{
                // 计算加成
                bonus = AddictiveLottery.calculateBonus(0)*0.6;
                break;
            }
            case 8:{
                // 计算加成
                bonus = AddictiveLottery.calculateBonus(0)*0.35;
                break;
            }
        }

        // 计算最终积分
        int finalPoints = (int) (Math.round(basePoints * bonus)*minutes/12);

        pointVo.setPoint(finalPoints);
        pointVo.setTotalPoint(one.getTotalReward()+finalPoints);
        pointVo.setDescription("基础积分"
                +basePoints+" + 加成"
                +(int)(bonus*100)+"% = "
                +finalPoints+"积分 (累计: "
                +(one.getTotalReward()+finalPoints)+"积分)");

//        //后更新积分
//        one.setTotalReward(one.getTotalReward()+finalPoints);
//        this.updateById(one);

        return pointVo;
    }

    @Override
    @Async("taskExecutor")
    public void saveReward(Integer reward,Integer tagId) {
        LambdaQueryWrapper<ScheduleReward> qw = new LambdaQueryWrapper<>();
        qw.eq(ScheduleReward::getRecordDate, LocalDate.now());
        ScheduleReward one = this.getOne(qw);

        if(tagId==1){
            // 计算工作学习轮次
            if(one.getConCount()==6){
                one.setConCount(1);
            }else{
                one.setConCount(one.getConCount()+1);
            }
        }
        //后更新积分
        one.setTotalReward(one.getTotalReward()+reward);
        this.updateById(one);
    }

    @Override
    @Async("taskExecutor")
    public Integer saveHabitReward() {

        Integer draw = LuckyDraw.draw();
        LambdaQueryWrapper<ScheduleReward> qw = new LambdaQueryWrapper<>();
        qw.eq(ScheduleReward::getRecordDate, LocalDate.now());
        ScheduleReward one = this.getOne(qw);
        if(Objects.isNull(one)) return 0;
        one.setTotalReward(one.getTotalReward()+draw);
        this.updateById(one);
        log.info("习惯打卡奖励:{}",one.getTotalReward());
        return draw;
    }


    @Override
    public ScheduleReward getDetail() {

        LambdaQueryWrapper<ScheduleReward> qw = new LambdaQueryWrapper<>();
        qw.eq(ScheduleReward::getRecordDate, LocalDate.now());
        ScheduleReward one = this.getOne(qw);
        if(Objects.isNull(one)) return null;
        log.info("今日奖励:{}",one.getTotalReward());
        return one;
    }

    @Override
    public void consume(RewardQuery query) {

        ScheduleReward byId = this.getById(query.getId());
        if(Objects.isNull(byId)) return;
        byId.setTotalReward(byId.getTotalReward()+query.getMinutes());
        this.updateById(byId);
    }

    @Override
    public void autoConsume(Integer tagId, Integer minutes) {
        try {
            if(tagId == 2){
                LambdaQueryWrapper<ScheduleReward> qw = new LambdaQueryWrapper<>();
                qw.eq(ScheduleReward::getRecordDate, LocalDate.now());
                ScheduleReward one = this.getOne(qw);
                if(Objects.isNull(one)) return ;
                one.setTotalReward(one.getTotalReward()-minutes);
//                if(one.getTotalReward()>=minutes){
//                    one.setTotalReward(one.getTotalReward()-minutes);
//                }else{
//                    one.setTotalReward(0);
//                }
                this.updateById(one);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void autoReward(Integer minutes) {
        try {
            LambdaQueryWrapper<ScheduleReward> qw = new LambdaQueryWrapper<>();
            qw.eq(ScheduleReward::getRecordDate, LocalDate.now());
            ScheduleReward one = this.getOne(qw);
            if(Objects.isNull(one)) return ;
            one.setTotalReward(one.getTotalReward() + minutes);
            this.updateById(one);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void continuousWork(Integer tagId, Integer minutes) {
        try {
            if(tagId != 1 && minutes > 10){
                LambdaQueryWrapper<ScheduleReward> qw = new LambdaQueryWrapper<>();
                qw.eq(ScheduleReward::getRecordDate, LocalDate.now());
                ScheduleReward one = this.getOne(qw);
                if(Objects.isNull(one)) return ;
                one.setConCount(1);
                this.updateById(one);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    private Integer getMinutes() {

        LambdaQueryWrapper<ScheduleRecord> qw = new LambdaQueryWrapper<>();
        qw.orderByDesc(ScheduleRecord::getCreateTime)
                .last("LIMIT 1");
        ScheduleRecord one = scheduleRecordService.getOne(qw);

        Duration duration = Duration.between(one.getEndTime(), LocalDateTime.now());
        return (int) duration.toMinutes();
    }


}
